/**
 * WebSocket服务类
 * 用于实时获取订单状态和骑手位置信息
 * 与小程序端保持一致的协议
 */

import { getToken, getRiderId, isRider } from './auth';

// WebSocket 状态码
const WS_STATUS = {
  CONNECTING: 0,
  OPEN: 1,
  CLOSING: 2,
  CLOSED: 3,
};

// 消息类型 - 与小程序端保持一致
export const MESSAGE_TYPES = {
  USER_RIDER_ADDR_UPDATE: "USER_RIDER_ADDR_UPDATE", // 骑手位置更新
  USER_ORDER_ACCEPTED: "USER_ORDER_ACCEPTED", // 骑手接单
  USER_ORDER_PICKED: "USER_ORDER_PICKED", // 骑手取餐
  USER_ORDER_DELIVERED: "USER_ORDER_DELIVERED", // 骑手送达
  CONNECTION_STATUS: "CONNECTION_STATUS", // WebSocket连接状态
  USER_ORDER_URGENT: "USER_ORDER_URGENT", // 催单消息类型
};

class WebSocketService {
  private ws: WebSocket | null = null;
  private status = WS_STATUS.CLOSED;
  private listeners = new Map<string, Function[]>();
  private reconnectTimer: NodeJS.Timeout | null = null;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 5;
  private reconnectInterval = 3000; // 3秒重连间隔
  private lastConnectTime = 0;
  private minConnectInterval = 5000; // 最小连接间隔5秒
  private token: string | null = null; // 保存token
  private isReconnecting = false;
  private forceClose = false; // 是否是主动关闭
  private heartbeatTimer: NodeJS.Timeout | null = null;

  constructor() {
    this.startHeartbeat();
  }

  // 获取连接状态
  isConnected(): boolean {
    return this.status === WS_STATUS.OPEN;
  }

  // 通知连接状态变化
  private notifyConnectionStatus(isConnected: boolean) {
    const handlers = this.listeners.get(MESSAGE_TYPES.CONNECTION_STATUS) || [];
    handlers.forEach((handler) => {
      try {
        handler({
          connected: isConnected,
          timestamp: new Date().getTime(),
        });
      } catch (error) {
        console.error("[WebSocket] 状态通知处理错误:", error);
      }
    });
  }

  // 初始化连接 - Web端版本
  async connect(token: string) {
    if (!token) {
      console.error("[WebSocket] 无效的 token");
      return;
    }

    // 如果已经连接或正在连接中，则不重复连接
    if (
      this.status === WS_STATUS.OPEN ||
      this.status === WS_STATUS.CONNECTING
    ) {
      console.log("[WebSocket] 已经连接或正在连接中");
      return;
    }

    const now = Date.now();
    if (now - this.lastConnectTime < this.minConnectInterval) {
      console.log("[WebSocket] 连接请求过于频繁，已忽略");
      return;
    }

    this.token = token;
    this.lastConnectTime = now;
    this.forceClose = false;

    // 如果正在重连中，直接返回
    if (this.isReconnecting) {
      console.log("[WebSocket] 正在重连中，跳过本次连接请求");
      return;
    }

    // 如果已经有连接，先关闭
    if (this.ws) {
      console.log("[WebSocket] 关闭现有连接");
      this.close();
      // 等待连接完全关闭
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }

    console.log("[WebSocket] 开始建立连接...");
    this.isReconnecting = true;

    try {
      // Web端使用与小程序相同的URL格式
      let url;
      if (import.meta.env.DEV) {
        // 开发环境：通过Vite代理
        url = `ws://localhost:5173/ws?token=${encodeURIComponent(token)}`;
      } else {
        // 生产环境：直连
        url = `wss://www.buaa.fun/api/channel?token=${encodeURIComponent(token)}`;
      }

      console.log("[WebSocket] 连接URL:", url);
      
      this.status = WS_STATUS.CONNECTING;
      this.notifyConnectionStatus(false);

      // Web端使用原生WebSocket API
      this.ws = new WebSocket(url);
      this.initEventHandlers();

    } catch (error) {
      console.error("[WebSocket] 连接出错:", error);
      this.status = WS_STATUS.CLOSED;
      this.notifyConnectionStatus(false);
      this.isReconnecting = false;
      this.scheduleReconnect();
    }
  }

  // 初始化事件处理器 - Web端版本
  private initEventHandlers() {
    if (!this.ws) {
      console.error("[WebSocket] WebSocket实例未创建");
      return;
    }

    this.ws.onopen = () => {
      console.log("[WebSocket] 连接成功");
      this.status = WS_STATUS.OPEN;
      this.isReconnecting = false;
      this.reconnectAttempts = 0;
      this.notifyConnectionStatus(true);
    };

    this.ws.onclose = (event) => {
      console.log("[WebSocket] 连接关闭", event);
      this.status = WS_STATUS.CLOSED;
      this.ws = null;
      this.notifyConnectionStatus(false);

      // 只有在不是主动关闭的情况下才重连
      if (!this.forceClose && !this.isReconnecting) {
        this.scheduleReconnect();
      }
    };

    this.ws.onmessage = (event) => {
      try {
        console.log("[WebSocket] 收到原始消息:", event.data);

        if (typeof event.data !== "string") {
          console.error("[WebSocket] 收到非字符串消息:", event.data);
          return;
        }

        // 如果消息以 "Welcome" 开头，这是欢迎消息
        if (event.data.startsWith("Welcome")) {
          console.log("[WebSocket] 收到欢迎消息:", event.data);
          return;
        }

        try {
          // 尝试解析 JSON 消息
          const message = JSON.parse(event.data);
          console.log("[WebSocket] 解析后的消息:", message);
          this.handleMessage(message);
        } catch (error) {
          console.error("[WebSocket] JSON消息解析错误:", error, "原始数据:", event.data);
        }
      } catch (error) {
        console.error("[WebSocket] 消息处理错误:", error);
      }
    };

    this.ws.onerror = (error) => {
      console.error("[WebSocket] 连接错误:", error);
      this.status = WS_STATUS.CLOSED;
      this.ws = null;
      this.notifyConnectionStatus(false);

      // 只有在不是主动关闭的情况下才重连
      if (!this.forceClose && !this.isReconnecting) {
        this.scheduleReconnect();
      }
    };
  }

  // 消息处理
  private handleMessage(message: any) {
    const { type, content } = message;

    if (!type) {
      console.error("[WebSocket] 无效的消息格式", message);
      return;
    }

    console.log(`[WebSocket] 处理消息类型: ${type}`, content);

    // 特殊处理催单消息
    if (type === MESSAGE_TYPES.USER_ORDER_URGENT) {
      this.handleUrgentOrder(content || message);
      return;
    }

    // 获取该消息类型的所有监听器
    const handlers = this.listeners.get(type) || [];

    // 调用所有监听器
    handlers.forEach((handler) => {
      try {
        handler(content || message);
      } catch (error) {
        console.error(`[WebSocket] 处理消息 ${type} 时出错:`, error);
      }
    });
  }

  // 添加消息监听器
  on(type: string, handler: Function) {
    if (!this.listeners.has(type)) {
      this.listeners.set(type, []);
    }
    this.listeners.get(type)!.push(handler);
    console.log(`[WebSocket] 已添加 ${type} 类型的监听器`);
  }

  // 移除消息监听器
  off(type: string, handler: Function) {
    if (!this.listeners.has(type)) return;

    const handlers = this.listeners.get(type)!;
    const index = handlers.indexOf(handler);

    if (index !== -1) {
      handlers.splice(index, 1);
      console.log(`[WebSocket] 已移除 ${type} 类型的监听器`);
    }

    if (handlers.length === 0) {
      this.listeners.delete(type);
    }
  }

  // 安排重连
  private scheduleReconnect() {
    // 如果是主动关闭，则不重连
    if (this.forceClose) {
      console.log("[WebSocket] 连接被主动关闭，不进行重连");
      return;
    }

    // 已经有重连计划，或达到最大重连次数，或正在重连中
    if (
      this.reconnectTimer ||
      this.reconnectAttempts >= this.maxReconnectAttempts ||
      this.isReconnecting
    ) {
      return;
    }

    const currentTime = Date.now();
    const timeSinceLastConnect = currentTime - this.lastConnectTime;
    const delay = Math.max(this.reconnectInterval, this.minConnectInterval - timeSinceLastConnect);

    console.log(`[WebSocket] 将在 ${delay}ms 后尝试重连`);

    this.reconnectTimer = setTimeout(async () => {
      this.reconnectTimer = null;
      this.reconnectAttempts++;

      console.log(
        `[WebSocket] 尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})`
      );

      const token = this.token || localStorage.getItem("token");
      if (token) {
        this.isReconnecting = true;
        try {
          await this.connect(token);
        } finally {
          this.isReconnecting = false;
        }
      } else {
        console.error("[WebSocket] 无法获取token，停止重连");
      }
    }, delay);
  }

  // 关闭连接
  close() {
    this.forceClose = true; // 标记为主动关闭
    this.stopHeartbeat();

    if (this.ws && this.status !== WS_STATUS.CLOSED) {
      this.ws.close();
      console.log("[WebSocket] 连接已主动关闭");
    }

    // 清理状态
    this.status = WS_STATUS.CLOSED;
    this.ws = null;
    
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }

    this.notifyConnectionStatus(false);
  }

  // 启动心跳检测
  private startHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
    }
    this.heartbeatTimer = setInterval(() => {
      const status = this.isConnected() ? "已连接" : "未连接";
      const time = new Date().toLocaleTimeString();
      console.log(`[WebSocket] ${time} - 连接状态: ${status}`);
    }, 30000); // 30秒检查一次
  }

  // 停止心跳检测
  private stopHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }

  // 发送消息（如果需要的话）
  send(message: any) {
    if (this.isConnected()) {
      try {
        const data = typeof message === 'string' ? message : JSON.stringify(message);
        this.ws!.send(data);
        console.log("[WebSocket] 消息已发送:", data);
      } catch (error) {
        console.error("[WebSocket] 发送消息失败:", error);
      }
    } else {
      console.warn("[WebSocket] 连接未建立，无法发送消息");
    }
  }

  // 兼容原有API
  onOrderStatusUpdate?: (data: any) => void;
  onRiderLocationUpdate?: (data: any) => void;
  onConnectionStatusChange?: (connected: boolean) => void;
  onUrgentOrderReceived?: (data: any) => void; // 新增催单回调

  // 处理催单消息
  private handleUrgentOrder(data: any) {
    console.log('[WebSocket] 收到催单消息:', data);
    
    // 检查是否是骑手角色
    if (!isRider()) {
      console.log('[WebSocket] 当前用户不是骑手，忽略催单消息');
      return;
    }

    // 获取当前骑手ID
    const currentRiderId = getRiderId();
    if (!currentRiderId) {
      console.log('[WebSocket] 无法获取骑手ID，忽略催单消息');
      return;
    }

    // 检查催单消息是否针对当前骑手
    const targetRiderId = data.riderId || data.rider_id || data.targetRiderId;
    if (targetRiderId && targetRiderId.toString() !== currentRiderId.toString()) {
      console.log(`[WebSocket] 催单消息不是针对当前骑手 (目标骑手: ${targetRiderId}, 当前骑手: ${currentRiderId})`);
      return;
    }

    // 如果没有指定目标骑手ID，认为是广播消息，当前骑手可以接收
    console.log('[WebSocket] 催单消息针对当前骑手，触发回调');
    
    // 调用催单回调
    this.onUrgentOrderReceived?.(data);
    
    // 也通过消息监听器分发
    const handlers = this.listeners.get(MESSAGE_TYPES.USER_ORDER_URGENT) || [];
    handlers.forEach((handler) => {
      try {
        handler(data);
      } catch (error) {
        console.error('[WebSocket] 催单消息处理器执行错误:', error);
      }
    });
  }

  // 为了兼容原有的订单详情页面代码
  connectToOrder(orderId: number) {
    // 使用auth模块的getToken函数获取token
    const token = getToken();
    if (token) {
      this.connect(token);
      
      // 设置兼容的回调监听
      this.on(MESSAGE_TYPES.USER_RIDER_ADDR_UPDATE, (data: any) => {
        this.onRiderLocationUpdate?.(data);
      });
      
      this.on(MESSAGE_TYPES.USER_ORDER_ACCEPTED, (data: any) => {
        this.onOrderStatusUpdate?.(data);
      });
      
      this.on(MESSAGE_TYPES.USER_ORDER_PICKED, (data: any) => {
        this.onOrderStatusUpdate?.(data);
      });
      
      this.on(MESSAGE_TYPES.USER_ORDER_DELIVERED, (data: any) => {
        this.onOrderStatusUpdate?.(data);
      });
      
      this.on(MESSAGE_TYPES.CONNECTION_STATUS, (data: any) => {
        this.onConnectionStatusChange?.(data.connected);
      });
    } else {
      console.error("[WebSocket] 无法获取token，无法建立连接");
    }
  }

  // 为了兼容，保留原有的disconnect方法名
  disconnect() {
    this.close();
  }
}

// 创建全局WebSocket服务实例
export const wsService = new WebSocketService();
